package org.apereo.cas.authentication;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.apereo.cas.authentication.principal.DefaultPrincipalFactory;
import org.apereo.cas.authentication.principal.PrincipalFactory;
import org.apereo.cas.services.ServicesManager;
import java.util.function.Predicate;
import lombok.Getter;
import lombok.Setter;

/**
 * Base class for all authentication handlers that support configurable naming.
 * 所有支持可配置命名的身份验证处理程序的基类。
 * @author Marvin S. Addison
 * @since 4.0.0
 */
@Slf4j
@Getter
@Setter
public abstract class AbstractAuthenticationHandler implements AuthenticationHandler {

    /**
     * Factory to create the principal type.
     * 工厂以创建委托人类型。
     **/
    protected final PrincipalFactory principalFactory;

    /**
     * The services manager instance, as the entry point to the registry.
     * 服务管理器实例，作为注册表的入口点。
     **/
    protected final ServicesManager servicesManager;

    /**
     * Indicates whether this handler is able to support the credentials passed to
     * operate on it and validate. Default is true.
     * *指示此处理程序是否能够支持传递给的凭据
     * *对其进行操作和验证。默认值为true。
     */
    protected Predicate<Credential> credentialSelectionPredicate = credential -> true;

    /**
     * Sets the authentication handler name. Authentication handler names SHOULD be unique within an
     * {@link AuthenticationManager}, and particular implementations
     * may require uniqueness. Uniqueness is a best
     * practice generally.
     * *设置身份验证处理程序名称。身份验证处理程序名称在
     *
     * *{@link AuthenticationManager}，以及特定的实现
     *
     * *可能需要唯一性。独一无二是最好的
     *
     * *普遍练习。
     */
    private final String name;

    /**
     * Sets order. If order is undefined, generates a random order value.
     * Since handlers are generally sorted by this order, it's important that
     * order numbers be unique on a best-effort basis.
     * *设置顺序。如果订单未定义，则生成随机订单值。
     *
     * *由于处理程序通常按此顺序排序，因此
     *
     * *订单号在最大努力的基础上是唯一的。
     */
    private final int order;

    /**
     * Instantiates a new Abstract authentication handler.
     *实例化新的抽象身份验证处理程序。
     * @param name Handler name.
     * @param servicesManager the services manager.
     * @param principalFactory the principal factory
     * @param order the order
     */
    public AbstractAuthenticationHandler(final String name, final ServicesManager servicesManager,
                                         final PrincipalFactory principalFactory, final Integer order) {
        this.name = StringUtils.isNotBlank(name) ? name : getClass().getSimpleName();
        this.servicesManager = servicesManager;
        this.principalFactory = principalFactory == null ? new DefaultPrincipalFactory() : principalFactory;
        if (order == null) {
            this.order = RandomUtils.nextInt(1, Integer.MAX_VALUE);
        } else {
            this.order = order;
        }
    }
}
